package com.mpgame.database.mysql.services;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.ibatis.session.SqlSession;

import com.mpgame.common.utils.Log;
import com.mpgame.core.loader.SkillLoader;
import com.mpgame.core.model.Skill;
import com.mpgame.core.model.SkillType;
import com.mpgame.database.mysql.mapper.game.MonsterHotbarMapper;
import com.mpgame.database.mysql.mapper.game.MonsterMapper;
import com.mpgame.database.mysql.mapper.game.SkillsMapper;
import com.mpgame.database.mysql.model.game.MonsterStore;
import com.mpgame.database.mysql.model.game.Skills;
import com.mpgame.database.mysql.utils.MyBatisUtil;

public class GameBattleDataSvc {
    /**
     * 批量获取战斗开始所需的所有数据
     */
    public static class GameBattleStartData {
        public com.mpgame.database.mysql.model.game.Monster myMonster;
        public com.mpgame.database.mysql.model.game.Monster opponentMonster;
        public Skills mySkill1;
        public Skills mySkill2;
        public Skills mySkill3;
        public Skills mySkill4;
    }

    /**
     * 批量获取PVP匹配所需的数据
     */
    public static class GamePVPMatchData {
        public MonsterStore player1Monster;
        public MonsterStore player2Monster;
    }

    /**
     * 获取战斗开始所需的所有数据
     */
    public GameBattleStartData getBattleStartData(MonsterStore myMonsterStore, MonsterStore opponentMonsterStore) {
        SqlSession sqlSession = null;
        try {
            sqlSession = MyBatisUtil.getSqlSession();

            MonsterMapper monsterMapper = sqlSession.getMapper(MonsterMapper.class);
            SkillsMapper skillsMapper = sqlSession.getMapper(SkillsMapper.class);

            GameBattleStartData data = new GameBattleStartData();

            // 批量获取怪物基础信息
            data.myMonster = monsterMapper.selectById(myMonsterStore.getMonsterId());
            data.opponentMonster = monsterMapper.selectById(opponentMonsterStore.getMonsterId());

            // 批量获取技能信息
            data.mySkill1 = skillsMapper.selectById(myMonsterStore.getSkill1Id());
            data.mySkill2 = skillsMapper.selectById(myMonsterStore.getSkill2Id());
            data.mySkill3 = skillsMapper.selectById(myMonsterStore.getSkill3Id());
            data.mySkill4 = skillsMapper.selectById(myMonsterStore.getSkill4Id());

            return data;
        } catch (Exception e) {
            Log.err("批量获取战斗开始数据异常: " + e.getMessage());
            throw new RuntimeException("批量获取战斗开始数据异常", e);
        } finally {
            if (sqlSession != null) {
                sqlSession.close();
            }
        }
    }

    /**
     * 获取PVP匹配所需的数据
     */
    public GamePVPMatchData getPVPMatchData(int account1Id, int account2Id) {
        SqlSession sqlSession = null;
        try {
            sqlSession = MyBatisUtil.getSqlSession();

            MonsterHotbarMapper monsterHotbarMapper = sqlSession.getMapper(MonsterHotbarMapper.class);

            GamePVPMatchData data = new GamePVPMatchData();

            // 批量获取玩家精灵数据
            data.player1Monster = monsterHotbarMapper.selectMonsterStoreByPlayerIdAndSlot(account1Id, 0);
            data.player2Monster = monsterHotbarMapper.selectMonsterStoreByPlayerIdAndSlot(account2Id, 0);

            return data;
        } catch (Exception e) {
            Log.err("批量获取PVP匹配数据异常: " + e.getMessage());
            throw new RuntimeException("批量获取PVP匹配数据异常", e);
        } finally {
            if (sqlSession != null) {
                sqlSession.close();
            }
        }
    }

    /**
     * 批量获取技能信息（通过ID列表）
     */
    public Map<Integer, Skills> getSkillsByIds(List<Integer> skillIds) {
        SqlSession sqlSession = null;
        try {
            sqlSession = MyBatisUtil.getSqlSession();

            SkillsMapper skillsMapper = sqlSession.getMapper(SkillsMapper.class);
            Map<Integer, Skills> skillsMap = new HashMap<>();

            for (Integer skillId : skillIds) {
                if (skillId != null && skillId > 0) {
                    Skills skill = skillsMapper.selectById(skillId);
                    if (skill != null) {
                        skillsMap.put(skillId, skill);
                    }
                }
            }

            return skillsMap;
        } catch (Exception e) {
            Log.err("批量获取技能信息异常: " + e.getMessage());
            throw new RuntimeException("批量获取技能信息异常", e);
        } finally {
            if (sqlSession != null) {
                sqlSession.close();
            }
        }
    }

    /**
     * 批量加载Monster对象（包含所有技能信息）
     */
    public static class GameMonsterLoadData {
        public com.mpgame.core.model.Monster monster1;
        public com.mpgame.core.model.Monster monster2;
    }

    /**
     * 批量加载两个Monster对象，减少数据库查询次数
     */
    public GameMonsterLoadData loadMonsters(MonsterStore monsterStore1, MonsterStore monsterStore2) {
        SqlSession sqlSession = null;
        try {
            sqlSession = MyBatisUtil.getSqlSession();

            SkillsMapper skillsMapper = sqlSession.getMapper(SkillsMapper.class);

            GameMonsterLoadData data = new GameMonsterLoadData();

            // 收集所有需要查询的技能ID
            List<Integer> allSkillIds = Arrays.asList(
                    monsterStore1.getSkill1Id(), monsterStore1.getSkill2Id(),
                    monsterStore1.getSkill3Id(), monsterStore1.getSkill4Id(),
                    monsterStore2.getSkill1Id(), monsterStore2.getSkill2Id(),
                    monsterStore2.getSkill3Id(), monsterStore2.getSkill4Id());

            // 批量获取所有技能信息
            Map<Integer, Skills> skillsMap = getSkillsByIds(allSkillIds);

            // 加载第一个Monster
            data.monster1 = loadMonsterFromStore(monsterStore1, skillsMap);

            // 加载第二个Monster
            data.monster2 = loadMonsterFromStore(monsterStore2, skillsMap);

            return data;
        } catch (Exception e) {
            Log.err("批量加载Monster对象异常: " + e.getMessage());
            throw new RuntimeException("批量加载Monster对象异常", e);
        } finally {
            if (sqlSession != null) {
                sqlSession.close();
            }
        }
    }

    /**
     * 从MonsterStore和技能Map中加载Monster对象
     */
    private com.mpgame.core.model.Monster loadMonsterFromStore(MonsterStore monsterStore,
            Map<Integer, Skills> skillsMap) {
        Skill s1 = loadSkill(skillsMap.get(monsterStore.getSkill1Id()));
        Skill s2 = loadSkill(skillsMap.get(monsterStore.getSkill2Id()));
        Skill s3 = loadSkill(skillsMap.get(monsterStore.getSkill3Id()));
        Skill s4 = loadSkill(skillsMap.get(monsterStore.getSkill4Id()));

        com.mpgame.core.model.Monster monster = new com.mpgame.core.model.Monster(
            monsterStore.getLv(),
            0,
            monsterStore.getMeleeAtk(), monsterStore.getMagicAtk(),
            monsterStore.getMeleeDef(), monsterStore.getMagicDef(),
            monsterStore.getSpeed(), monsterStore.getHealth(),
            s1, s2, s3, s4);

        return monster;
    }

    /**
     * 将数据库中的Skills转换为core模型中的Skill
     */
    private Skill loadSkill(Skills skillInDB) {
        if (skillInDB == null)
            return null;

        SkillType skillType;
        switch (skillInDB.getEffect()) {
            case 0:
                skillType = SkillType.MELEE;
                break; // 物攻
            case 1:
                skillType = SkillType.MAGIC;
                break; // 特攻
            case 2:
                skillType = SkillType.PROP;
                break; // 强化
            default:
                skillType = SkillType.MELEE;
                break;
        }

        Skill skill = SkillLoader.loadSkill(
            skillInDB.getFamilyId(),
            skillInDB.getPower(),
            skillInDB.getPriority(),
            skillInDB.getPp(),
            (double) skillInDB.getAccuracy() / 100,
            skillType,
            skillInDB.getAdditionalEffect());
        if(skill != null) skill.setIdentifier(skillInDB.getName());

        return skill;
    }
}
